import { Empty, Flex, Loading, Toast } from "@taroify/core";
import { View } from "@tarojs/components";
import { useEffect } from "react";
import { useNavigationBar } from "taro-hooks";
import { match, __ } from 'ts-pattern';
import { UsePromiseResult } from "./flora-client-hooks";

// 设置当前页面标题。
export function usePageTitle(title: string) {
  const [, { setTitle }] = useNavigationBar();
  useEffect(() => {
    setTitle(title);
  }, [title]);
}

export function DrawPromiseResult<T, E>(props: {
  result: UsePromiseResult<T, E>,
  drawLoading?: () => React.ReactNode,
  drawError?: (error: E) => React.ReactNode,
  children: (result: T) => React.ReactNode,
}) {
  const drawError = props.drawError || ((error: E) => {
    const MyEmpty: any = Empty;  // https://github.com/mallfoundry/taroify/issues/131
    return (
      <MyEmpty>
        {[
          <Empty.Image src="error" />,
          <Empty.Description>加载错误: {JSON.stringify({ error })}</Empty.Description>,
        ] as any}
      </MyEmpty>);
  });

  const drawLoading = props.drawLoading || (() => <Flex justify="center" style={{ paddingTop: '20px' }}><Loading /></Flex>);

  switch (props.result.status) {
    case 'pending': {
      return <View>{drawLoading()}</View>;
    }
    case 'rejected': {
      return <View>{drawError(props.result.error)}</View>;
    }
    case 'resolved': {
      return <View>
        {props.children(props.result.result)}
      </View>
    }
  }
}

export type SupportedResult =
  {
    status: 'ok',
    result: {
      error_msg: string,
      status: 'error',
    },
  } | {
    status: 'ok',
    result: {
      status: unknown,
    }
  }


export async function liftError<T extends SupportedResult>(p: Promise<T>): Promise<T> {
  const r: SupportedResult = await p;
  const errorMsg = match(r)
    .with({
      status: 'ok',
      result: {
        status: 'error',
        error_msg: __.string,
      },
    }, r => {
      return r.result.error_msg;
    }).otherwise(() => '');

  if (errorMsg) {
    throw new Error(errorMsg);
  }
  return r as T;
}

export function ToastPromise(p: Promise<SupportedResult>, successMsg?: string) {
  liftError(p).then(() => {
    Toast.open({
      message: successMsg || '成功',
    })
  }).catch(e => {
    Toast.open({
      message: `错误 ${e}`,
    })
  });
}
